package controller;

import java.awt.event.WindowEvent;
import java.util.ArrayList;
import view.ContactForm;
import java.awt.BorderLayout;
import java.awt.event.WindowListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import model.Contact;
import model.ContactGroup;
import model.ContactGroupManager;
import model.ContactNotFoundException;
import persistence.ContactDAO;
import persistence.ContactGroupDAO;
import persistence.PersistenceUtil;
import view.ContactDetailedViewPanel;
import view.ContactFormDelegate;
import view.ContactGroupForm;
import view.ContactGroupFormDelegate;
import view.ContactGroupListDelegate;
import view.ContactGroupListPanel;
import view.ContactListDelegate;
import view.ContactListPanel;
/**
 * 
 * @author hbriand
 *
 * @class ContactManager
 * @desc This is the controller of the desktop application. It manages the views 
 * 		and the connection between views and models (through ContactGroupManager).
 */
public class ContactManager implements WindowListener, ContactGroupListDelegate, ContactListDelegate, ContactGroupFormDelegate, ContactFormDelegate {

    private JFrame frame;
    private ContactGroupListPanel currentGroupContactListPanel;
    private ContactListPanel currentContactListPanel;
    private ContactDetailedViewPanel currentContactDetailedViewPanel;

    /**
     * Launch the application.
     */
    public ContactManager() {
        this.frame = new JFrame();
        this.frame.setSize(800, 600);
        this.frame.setLayout(new BorderLayout());
        this.frame.addWindowListener(this);
        this.currentGroupContactListPanel = new ContactGroupListPanel();
        this.currentContactListPanel = new ContactListPanel();
        this.currentContactDetailedViewPanel = new ContactDetailedViewPanel();
    }

    /**
     * @method show
     * 
     * @desc Shows the main window
     */
    public void show() {
        this.currentGroupContactListPanel.setGroupContactList((ArrayList<ContactGroup>) ContactGroupManager.getInstance().getGroupList());
        this.currentContactListPanel.setDelegate(this);
        this.currentGroupContactListPanel.setDelegate(this);
        this.draw();
        this.frame.setVisible(true);
    }

    /**
     * @method redraw
     * 
     * @desc refreshes the views with new datas
     */
    
    public void redraw() {
        this.currentGroupContactListPanel.redraw();
        this.currentContactListPanel.redraw();
        this.currentContactDetailedViewPanel.redraw();
        this.draw();
        this.frame.setVisible(true);
    }

    /**
     * @method draw
     * @desc Designs the view
     */
    private void draw() {
        this.frame.add(this.currentGroupContactListPanel, BorderLayout.LINE_START);
        if (this.currentContactListPanel.hasElements()) {
            this.frame.add(this.currentContactListPanel, BorderLayout.CENTER);
        }
        if (this.currentContactDetailedViewPanel.hasContact()) {
            this.frame.add(this.currentContactDetailedViewPanel, BorderLayout.LINE_END);
        }
    }


    
    
    // Following methods are implementations of the various interfaces used by the views
    // to avoid cyclical dependencies
    
    
    
    
    
    public void contactGroupSelected(ContactGroup selected) {
        ContactGroupDAO cgDAO = new ContactGroupDAO();
        PersistenceUtil.beginTransaction();
        selected = cgDAO.merge(selected);
        System.out.println("contactGroupSelected : " + selected.getName());
        if (this.frame.isAncestorOf(this.currentContactListPanel)) {
            this.frame.remove(this.currentContactListPanel);
            if (this.frame.isAncestorOf(this.currentContactDetailedViewPanel)) {
                this.frame.remove(this.currentContactDetailedViewPanel);
            }
        }
        this.currentContactListPanel.setContactList(selected.getSortedContactList());
        PersistenceUtil.commitTransaction();
        //cgDAO.close();


        this.frame.add(this.currentContactListPanel, BorderLayout.CENTER);
        this.frame.setVisible(true);
    }
    
    public void contactDefaultGroupSelected() {
        System.out.println("contactGroupSelected : All");
        if (this.frame.isAncestorOf(this.currentContactListPanel)) {
            this.frame.remove(this.currentContactListPanel);
            if (this.frame.isAncestorOf(this.currentContactDetailedViewPanel)) {
                this.frame.remove(this.currentContactDetailedViewPanel);
            }
        }
        this.currentContactListPanel.setContactList(ContactGroupManager.getInstance().getAllSortedContacts());


        this.frame.add(this.currentContactListPanel, BorderLayout.CENTER);
        this.frame.setVisible(true);
    } 

    public void contactSelected(Contact selected) {
        System.out.println("contactSelected : " + selected.fullName());
        if (this.frame.isAncestorOf(this.currentContactDetailedViewPanel)) {
            this.frame.remove(this.currentContactDetailedViewPanel);
        }
        this.currentContactDetailedViewPanel.setContact(selected);
        this.frame.add(this.currentContactDetailedViewPanel, BorderLayout.LINE_END);
        this.frame.setVisible(true);
    }

    public void deleteContactGroup(ContactGroup selected) {
        System.out.println("deleteContactGroup");
        ContactGroupManager.getInstance().deleteGroup(selected);
        this.frame.remove(this.currentContactDetailedViewPanel);
        this.frame.remove(this.currentContactListPanel);
        this.redraw();
    }

    public void editContactGroup(ContactGroup selected) {
        ContactGroupForm cgForm = new ContactGroupForm(selected);
        cgForm.setDelegate(this);
        cgForm.show();
    }

    public void addContactGroup() {
        ContactGroupForm cgForm = new ContactGroupForm();
        cgForm.setDelegate(this);
        cgForm.show();
    }

    public void deleteContact(Contact selected) {
        System.out.println("Deleting contact : " + selected.fullName());
        try {
            ContactGroupManager.getInstance().deleteContact(selected);
            this.frame.remove(this.currentContactDetailedViewPanel);
            this.redraw();
        } catch (ContactNotFoundException ex) {
            Logger.getLogger(ContactManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void editContact(Contact selected) {
        ContactForm cgForm = new ContactForm(selected);
        cgForm.setDelegate(this);
        cgForm.show();
    }

    public void addContact() {
        ContactForm cgForm = new ContactForm();
        cgForm.setDelegate(this);
        cgForm.show();
    }

    public void contactGroupFormAdd(ContactGroup currentGroup) {
        System.out.println("contactGroupFormAdd");
        ContactGroupManager.getInstance().saveGroup(currentGroup);
        this.redraw();
    }

    public void contactGroupFormCancel() {
        System.out.println("contactGroupFormCancel");
        this.redraw();
    }

    public void contactFormCancel() {
        System.out.println("contactGroupCancel");
        this.redraw();
    }

    public void contactFormAdd(Contact currentContact) {
        System.out.println("contactFormAdd "+ currentContact.fullName());
        ContactGroup currentSelectedGroup = this.currentGroupContactListPanel.getCurrentSelectedGroup();
        currentContact.setGroup(currentSelectedGroup);
        ContactGroupManager.getInstance().AddNewContact(currentContact);

        this.redraw();
    }


    /* Window Listener interface methods */
    public void windowOpened(WindowEvent e) {
    }

    public void windowClosing(WindowEvent e) {
        System.exit(0);
    }

    public void windowClosed(WindowEvent e) {
    }

    public void windowIconified(WindowEvent e) {
    }

    public void windowDeiconified(WindowEvent e) {
    }

    public void windowActivated(WindowEvent e) {
    }

    public void windowDeactivated(WindowEvent e) {
    }
}
